/******************
* playLayer
* 
* For this layer, I envision on large layer with a much simpler timeline (horizontal only) with
* no zoom capabilities (autofit).  A simple text display shows how many controllers are loaded,
* and the "current" value for each controller.  Playback controls should include Play (1x), Pause,
* Stop (reset to frame 0), Fast Forward (*2... up to *16), Slow (/2...down to 1/16), Rewind (*2...up
* to -16).
* 
* The name of the input file being streamed should be prominent... the EDIT layer needs a command
* similar to the LW "Send to Layout"... or maybe Export does that automatically.
* Other controls should include a toggle for looping (as well as setting loop delay).
******************/


//something weird is going on where playLayer class variables are getting
//constantly reset, so I've temporarily pulled them out as globals
int PLAYNUMCONTROL;
int[] PLAYNUMANALOG = {0};
int[] PLAYNUMDIGITAL = {0};
dataPoint[] PLAYDATA;
int PLAYDURATION = 10000;
boolean ISPLAYING = false;
float PLAYHEAD = 0.0;
float PLAYSCALE = 1.0;
float PLAYSLIDER = 0.0;
PGraphics PLAYTIMELINE;
boolean PLAYDRAG = false;

class playLayer extends Layer
{
  float playSpeed = 1.0;  //16,8,4,2,1,1/2,1/4,1/8,1/16,0,-1,-2,-4,-8,-16

  String path = "";

  boolean LOADED = false;
  boolean LOOP = true;
  int LOOPDELAY = 1000;  //number of seconds before looping
    
  dataPoint[] currentState;  //the current value for each controller
  
  int lastTime;

  boolean popup = false;
  
  playLayer()
  {
    super(44,44,width-44,height-44,0);
    RESIZEENABLED = false;
    MINX = 44;
    MINY = 44;
    
    PLAYDATA = new dataPoint[0];
    drawTimeline();
  }
  
  playLayer(dataFile df)
  {
    super(44,44,width-44,height-44,0);
    RESIZEENABLED = false;
    MINX = 44;
    MINY = 44;
    
    PLAYDATA = df.data;
    PLAYNUMCONTROL = 1;
    PLAYNUMDIGITAL = new int[] {df.numDigital};
    PLAYNUMANALOG = new int[] {df.numAnalog};
    PLAYDURATION = df.getDuration();
    drawTimeline();
  }
  
  boolean mDraw()
  {
    float timePassed = millis() - lastTime;
    lastTime = millis();
    
    if(ISPLAYING) advanceTime(timePassed * playSpeed);
    dataPoint[] dp = getZeroPoints(PLAYNUMCONTROL);
    for(int i = 0; i < PLAYDATA.length; i++)
    {
      if(PLAYHEAD >= PLAYDATA[i].TIME) dp[PLAYDATA[i].CONTROLLER] = PLAYDATA[i];      
    }
    
    //println("PLAYHEAD: " + PLAYHEAD);
    for(int i = 0; i < dp.length; i++)
    {
      boolean[] dig = new boolean[PLAYNUMDIGITAL[i]];
      Arrays.fill(dig,false);
      for(int j = 0; j < PLAYNUMDIGITAL[i]; j++)
      {
        if(dp[i].DIGITAL[j] == 1) dig[j] = true;
      }
      if(ISPLAYING) transmitUDP(i,dig,dp[i].ANALOG);
    }
    
    pg.beginDraw();
    pg.background(BORDERCOLOR);
    pg.fill(FILLCOLOR);
    pg.noStroke();
    pg.rect(3,3,pg.width-6,pg.height-6);
    pg.textFont(font,20);
    pg.stroke(255);
    pg.fill(255);
    //draw the current state of things...
    for(int i = 0; i < dp.length; i++)
    {
      pg.text("Controller " + i + ":" + dp[i].getData(),10,25*i + 50);
    }
    
    //draw the timeline
    pg.image(PLAYTIMELINE,10,h-40);
    
    if(PLAYDRAG)
    {
      PLAYSLIDER = mouseX-x-15;
      PLAYHEAD = (mouseX-x-15) * TUNIT / PLAYSCALE;
    }
    
    //draw the position
    pg.stroke(BUTTONSTROKE);
    pg.fill(BUTTONSTROKE);
    PLAYSLIDER = 10 + PLAYHEAD/TUNIT*PLAYSCALE;
    pg.rect(PLAYSLIDER,h-50,10,40);
    pg.endDraw();
    pg.modified = true;
    
    doCursor();

        

    
    return DONE;
  }
  
  dataPoint[] getZeroPoints(int nc)
  {
    dataPoint[] r = new dataPoint[nc];
    for(int i = 0; i < nc; i++)
    {
      String[] d = new String[2 + PLAYNUMDIGITAL[i] + PLAYNUMANALOG[i]];
      d[0] = i + "";
      d[1] = "0";
      for(int j = 0; j < PLAYNUMDIGITAL[i]; j++)
      {
        d[j+2] = "0";
      }
      for(int j = 0; j < PLAYNUMANALOG[i]; j++)
      {
        d[j+2+PLAYNUMDIGITAL[i]] = "127";
      }
      r[i] = new dataPoint(d,PLAYNUMDIGITAL[i],PLAYNUMANALOG[i]);
    }
    return r;    
  }
  
  void drawTimeline()
  {
    //println("HEY DRAW THE TIMELINE!");
    float widthNeeded = PLAYDURATION/TUNIT;
    float useW = w - 40;
    float hScale = useW/widthNeeded;    
    PLAYSCALE = hScale;

    widthNeeded = PLAYDURATION/TUNIT*hScale;
    useW = w - 40;
    
    PLAYTIMELINE = createGraphics((int)max(useW,widthNeeded+10),30,JAVA2D);
    PLAYTIMELINE.beginDraw();
    PLAYTIMELINE.background(color(24,50,90));
    
    //figure out what unit of measure is appropriate...
    float displayAmt = PLAYDURATION;
    
    int[] unitList = {10,20,50};
    int whichUnit = 0;
    while((int)displayAmt / unitList[whichUnit] > 10)
    {
      whichUnit++;
      if(whichUnit == 3)
      {
        whichUnit = 0;
        for(int i = 0; i < 3; i++)
        {
          unitList[i] *= 10;
        }
      }
    }

    int unit = unitList[whichUnit];

    int numUnits = ((int)PLAYDURATION /  (int)unit);
    //TUNIT*PLAYSCALE
    float spacing = unit/TUNIT*PLAYSCALE;//(int)widthNeeded / numUnits;
    PLAYTIMELINE.textFont(font,12);
    PLAYTIMELINE.textAlign(CENTER);
    PLAYTIMELINE.stroke(114,159,207);
    for(int i = 0; i < PLAYDURATION / unit + 1; i++)
    {
      if(i*unit > PLAYDURATION) break;
      PLAYTIMELINE.text("" + (int)(i*unit),5 + spacing*i,PLAYTIMELINE.height-5);
//      println((int)(i*unit) + "   " + (5 + spacing * i));
//      println(5 + (i*unit)/TUNIT*PLAYSCALE);
      for(float j = 0;j < 10; j++)
      {
        PLAYTIMELINE.line(5+spacing*i+(float)spacing*j/10.0,PLAYTIMELINE.height-25,5+spacing*i+(float)spacing*j/10.0,PLAYTIMELINE.height-(j%5 == 0?17:21));
        if(i*unit + j/10.0*(float)unit  >= PLAYDURATION) break;
      }
    }
    
    PLAYTIMELINE.endDraw();
    PLAYTIMELINE.modified = true;
  }
  
  void mPress()
  {
    if(mouseX - x > PLAYSLIDER && mouseX - x < PLAYSLIDER + 10 && mouseY - y > h-40 && mouseY-y < h-10) PLAYDRAG = true;
  }
  
  void mDrag()
  {
  }

  void mRelease()
  {
    PLAYDRAG = false;
  }
  
  void mKeyUp()
  {
    advanceTime(1000);
    println(PLAYHEAD + " " + PLAYSCALE + " " + PLAYHEAD/TUNIT*PLAYSCALE);
    println(15 + PLAYHEAD/TUNIT*PLAYSCALE);  //,h/2-20,10,40);    
    println((mouseX - x) / (15 + PLAYHEAD/TUNIT*PLAYSCALE));
  }
  
  void advanceTime(float i)
  {
    if(i == 0) return;
    PLAYHEAD += i;

    if(PLAYHEAD > PLAYDURATION && !LOOP) stop();
    
    if(PLAYHEAD > PLAYDURATION && LOOP){

        PLAYHEAD -= PLAYDURATION;

    }

  }
    
  void play()
  {
    println("Play called! ("+LOADED+")");
    if(playSpeed != 1 || !ISPLAYING)
    {
      playSpeed = 1.0;
      ISPLAYING = true;
      lastTime = millis();
      println("playSpeed: " + playSpeed);
      return;   
    } 
    ISPLAYING = false;
    println("pause...");
  }  
  
  void pause()
  {
    ISPLAYING = false;
  }
  
  void stop()
  {
    ISPLAYING = false;
    PLAYHEAD = 0;
  }
  
  void seekLeft()
  {
    if(playSpeed < 0 && playSpeed > -16) playSpeed *= 2;
    if(playSpeed > 0) playSpeed = -1;
  }
  
  void seekRight()
  {
    if(playSpeed > 0 && playSpeed < 16) playSpeed *= 2;
    if(playSpeed < 0) playSpeed = 2;
  }
  
  void skipLeft()
  {
    //CURRENTKEY--;
    //if(CURRENTKEY < 0) CURRENTKEY = PLAYDATA.length - 1;
  }
  
  void skipRight()
  {
    //CURRENTKEY++;
    //if(CURRENTKEY == PLAYDATA.length) CURRENTKEY = 0;
  }
  
  void openFile(String s)
  {
     path = s;
     String[] preData = loadStrings(path);
     try {
       PLAYNUMCONTROL = Integer.parseInt(preData[0]);
       PLAYNUMDIGITAL = new int[PLAYNUMCONTROL];
       PLAYNUMANALOG  = new int[PLAYNUMCONTROL];
       String[] dig = Explode.explode(" ",preData[1]);
       String[] ana = Explode.explode(" ",preData[2]);
       for(int i = 0; i < PLAYNUMCONTROL; i++)
       {
         PLAYNUMDIGITAL[i] = Integer.parseInt(dig[i]);
         PLAYNUMANALOG[i]  = Integer.parseInt(ana[i]);     
       }
     } catch (NumberFormatException e) {
       popWarn("Could not load file!");
       return;
     }
     //println(PLAYNUMDIGITAL + " " + PLAYNUMANALOG);
     PLAYDATA = new dataPoint[preData.length - 3];
     for(int i = 3; i < preData.length; i++)
     {
       String[] st = Explode.explode(" ",preData[i]);
      try {
         int c = Integer.parseInt(st[0]);
         PLAYDATA[i-3] = new dataPoint(st,PLAYNUMDIGITAL[c],PLAYNUMANALOG[c]);
      }catch (NumberFormatException e){
        popWarn("Error loading PLAYDATA!");
        PLAYDATA = null;
        return;
      }
     }
     PLAYDURATION = PLAYDATA[PLAYDATA.length-1].TIME + LOOPDELAY;
     drawTimeline();
     LOADED = true;
     println("FILE LOADED! (" + LOADED + ")");
  } 
}
